﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Styx.Helpers;
using System.Globalization;
using System.IO;
using Styx.WoWInternals;
using Styx.Logic.Pathing;
namespace RoutesAutomator
{
    public enum ProfileType
    {
        HB,
        GB
    }
    public partial class MainForm : Form
    {
        private bool WoWRoutersAutoLoaded;
        private class Const
        {
            public const string StartBotButtonLabel = "&Start Bot";
            public const string StopBotButtonLabel = "&Stop Bot";
        }
        static private object DoImportLock = new object();

        private bool loadingRoutes;
        static CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
        UTF8Encoding encoding = new UTF8Encoding();

        public MainForm()
        {
            InitializeComponent();
            ProfileTypeCombo.SelectedIndex = 1;
            folderBrowserDialog.SelectedPath = RoutesAutomator.Instance.MySettings.LastFolder;
            Utility.Write("Enabled");
            PulseTimer.Enabled = true;
            //DoImport();
        }

        Thread importThread;
        private void ImportBut_Click(object sender, EventArgs e)
        {
            if (Bot.IsRunning)
                DoImport();
            else
            {
                const string message = "Cannot refresh list because the bot is not running. Start the bot then try again.";
                Utility.Write(Color.Red, message);
                MessageBox.Show(message, Constants.DisplayName,
                                MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
            }
        }
        void DoImport()
        {
            try
            {
                lock (DoImportLock)
                {
                    if (loadingRoutes) return;
                    loadingRoutes = true;
                }
                Utility.Write("Loading routes from World of Warcraft Routes Addon.");
                updateProgressBar(0);
                DisabelControls();
                importThread = new Thread(RoutesAutomator.Instance.ImportRoutes);
                importThread.IsBackground = true;
                RoutesAutomator.Instance.OnImportDone += new EventHandler(Instance_OnImportDone);
                Utility.WriteDebug(Color.Red, "");
                importThread.Start();            
            }
            catch (Exception ex)
            {
                Utility.WriteDebug(Color.Red, ex.ToString());
            }
        }
        void EnableControls()
        {
            progressBar.Visible = false;
            ImportBut.Enabled = true;
            ExportBut.Enabled = true;
            ImportBut.Visible = true;
            ProfileTypeCombo.Enabled = true;
            HeightNumeric.Enabled = true;
            RouteList.Enabled = true;
            UnderWaterCheck.Enabled = true;
            btnBotEnabler.Visible = true;
            btnBotEnabler.Enabled = true;
        }

        void DisabelControls()
        {
            progressBar.Visible = true;
            ImportBut.Visible = false;
            ImportBut.Enabled = false;
            ExportBut.Enabled = false;
            ProfileTypeCombo.Enabled = false;
            HeightNumeric.Enabled = false;
            RouteList.Enabled = false;
            UnderWaterCheck.Enabled = false;
            btnBotEnabler.Visible = false;
            btnBotEnabler.Enabled = false;
        }

        delegate void BotEnablerSetTextDelegate(string value);
        void btnBotEnablerSetText(string value)
        {
            if (btnBotEnabler.InvokeRequired)
                btnBotEnabler.BeginInvoke(new BotEnablerSetTextDelegate(btnBotEnablerSetText), value);

            btnBotEnabler.Text = value;
        }

        delegate void invokeDelegate();
        
        void Instance_OnImportDone(object sender, EventArgs e)
        {
            if (RouteList.InvokeRequired)
                RouteList.BeginInvoke(new invokeDelegate(showRoutes));
            else
                showRoutes();

            Utility.Write("Finished loading routes from World of Warcraft Routes Addon.");
            loadingRoutes = false;
        }

        //private delegate bool IsVisibleDelegate();
        //public bool IsVivible()
        //{
        //    if (InvokeRequired)
        //        BeginInvoke(new IsVisibleDelegate(IsVivible));

        //    return Visible;
        //}
        delegate void pBarDelegate(int value);
        public void UpdateProgressBar(int value)
        {
            if (progressBar.InvokeRequired)
                progressBar.BeginInvoke(new pBarDelegate(updateProgressBar), value);
            else
                updateProgressBar(value);
        }

        void updateProgressBar(int value)
        {
            if (value > 100)
                value = 100;
            progressBar.Value = value;
        }

        void showRoutes()
        {
            EnableControls();
            RouteList.Rows.Clear();
            foreach (Route r in RoutesAutomator.Instance.Routes)
            {
                DataGridViewRow row = new DataGridViewRow();
                DataGridViewTextBoxCell cell = new DataGridViewTextBoxCell();
                cell.Value = r.Name;
                cell.Tag = r;
                row.Cells.Add(cell);
                RouteList.Rows.Add(row);
            }
        }
        private void ExportProfile(string exportFileName, ProfileType profileType)
        {
            if (!string.IsNullOrEmpty(exportFileName))
            {
                string saveLocation = Path.GetFullPath(exportFileName);
                RoutesAutomator.Instance.MySettings.LastFolder = saveLocation;
                RoutesAutomator.Instance.MySettings.Save();
                foreach (DataGridViewRow row in RouteList.SelectedRows)
                {
                    var route = (Route)row.Cells[0].Tag;
                    using (FileStream fs = File.Open(exportFileName, FileMode.Create))
                    {
                        if (profileType==ProfileType.GB)
                            fs.Write(encoding.GetBytes(GBprefix), 0, GBprefix.Length);
                        else
                            fs.Write(encoding.GetBytes(HBprefix), 0, HBprefix.Length);

                        int height = (int)HeightNumeric.Value;
                        List<WoWPoint> waypoints = height >= 0 && !UnderWaterCheck.Checked ? route.HighPoints : route.LowPoints;
                        waypoints = ReverseCheck.Checked ? waypoints.Reverse<WoWPoint>().ToList() : waypoints;
                        for (int i = 0; i < waypoints.Count; i++)
                        {
                            var newPoint = waypoints[i];
                            newPoint.Z += height;
                            if (UnderWaterCheck.Checked && route.HighPoints[i].Z >= newPoint.Z)
                                newPoint.Z = route.HighPoints[i].Z - 5;
                            string buf;
                            if (ProfileTypeCombo.SelectedIndex == 0)
                                buf = string.Format(culture, "    <Waypoint>{0} {1} {2}</Waypoint>{3}",
                                    newPoint.X, newPoint.Y, newPoint.Z, Environment.NewLine);
                            else
                                buf = string.Format(culture, "    <Hotspot X=\"{0}\" Y=\"{1}\" Z=\"{2}\" />{3}",
                                    newPoint.X, newPoint.Y, newPoint.Z, Environment.NewLine);
                            fs.Write(encoding.GetBytes(buf), 0, buf.Length);
                        }
                        if (profileType == ProfileType.GB)
                            fs.Write(encoding.GetBytes(GBpostfix), 0, GBpostfix.Length);
                        else
                            fs.Write(encoding.GetBytes(HBpostfix), 0, HBpostfix.Length);
                    }
                    //Utility.Write("Profile Created {0}", exportFileName);
                }
            }
        }
        private void ExportBut_Click(object sender, EventArgs e)
        {
            folderBrowserDialog.SelectedPath = RoutesAutomator.Instance.MySettings.LastFolder;
            if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK && RouteList.SelectedRows != null)
            {
                RoutesAutomator.Instance.MySettings.LastFolder = folderBrowserDialog.SelectedPath;
                RoutesAutomator.Instance.MySettings.Save();
                foreach (DataGridViewRow row in RouteList.SelectedRows)
                {
                    ProfileType profileType = ProfileTypeCombo.SelectedIndex == 0 ? ProfileType.GB : ProfileType.HB;

                    //Route route = (Route)row.Cells[0].Tag;
                    string filename = Path.Combine(folderBrowserDialog.SelectedPath,
                        string.Format("{0}{1}.xml", row.Cells[0].Value, (profileType == ProfileType.GB) ? "[GB]" : "[HB]"));

                    ExportProfile(filename, profileType);

                    Utility.Write("Exported {0}", filename);
                }
            }
        }


        string HBprefix =
@"<HBProfile>
  <Name></Name>
  <MinDurability>0.4</MinDurability>
  <MinFreeBagSlots>1</MinFreeBagSlots>
  
  <MinLevel>1</MinLevel>
  <MaxLevel>86</MaxLevel>
  <Factions>99999</Factions>
  
  <MailGrey>False</MailGrey>
  <MailWhite>True</MailWhite>
  <MailGreen>True</MailGreen>
  <MailBlue>True</MailBlue>
  <MailPurple>True</MailPurple>
 
  <SellGrey>True</SellGrey>
  <SellWhite>True</SellWhite>
  <SellGreen>False</SellGreen>
  <SellBlue>False</SellBlue>
  <SellPurple>False</SellPurple>

	<Vendors>

	</Vendors>
	
	<Mailboxes>

	</Mailboxes>

  <Hotspots>
";
        string HBpostfix =
@"  </Hotspots>
</HBProfile>
";
        string GBprefix =
@"
<?xml version=""1.0""?>
<GlideProfile>
  <MinLevel>1</MinLevel>
  <MaxLevel>80</MaxLevel>
  <NaturalRun>True</NaturalRun>
  <LureMinutes>0</LureMinutes>
  <SkipWaypoints>True</SkipWaypoints>
  <Factions></Factions>
";
        string GBpostfix =
        @"</GlideProfile>
";

        private void btnBotEnabler_Click(object sender, EventArgs e)
        {
            try
            {

                if (Bot.IsRunning)
                {
                    Bot.Stop();
                    btnBotEnablerSetText(Const.StartBotButtonLabel);
                    Utility.Write("Stopped Bot");
                    //Utility.Write("The bot is currently running. You must stop it first.");
                }
                else
                {
                    string path = Path.GetDirectoryName(Assembly.GetAssembly(typeof(MainForm)).CodeBase);
                    path = path.Replace("file:\\", "");
                    string pathProfileFilename = Path.Combine(path, "RouteAutomatorHBProfile.xls");
                    ExportProfile(pathProfileFilename, ProfileType.HB);
                    Bot.ChangeBot(Constants.BotName.Gatherbuddy2);
                    Bot.LoadProfile(pathProfileFilename);
                    Bot.Start();
                    btnBotEnablerSetText(Const.StopBotButtonLabel);
                    Utility.Write("Started Bot");
                }

            }
            catch (Exception ex)
            {
                Utility.WriteDebug(Color.Red, ex.ToString());                
            }
        }

        public bool IsVisible { get; private set; }
        private void MainFormVisibleChanged(object sender, EventArgs e)
        {
            IsVisible = Visible;
        }

        private void PulseTimer_Tick(object sender, EventArgs e)
        {
            if (Bot.IsRunning)
            {
                if (!WoWRoutersAutoLoaded)
                {
                    WoWRoutersAutoLoaded = true;
                    DoImport();
                }

                btnBotEnabler.Text = Const.StopBotButtonLabel;
            }
            else
            {
                btnBotEnabler.Text = Const.StartBotButtonLabel;
            }

        }


    }
}
